package com.pro.common.modules.service.dependencies.commondata.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.opencsv.CSVWriter;
import com.pro.common.api.auth.model.UserDataQuery;
import com.pro.common.api.exception.BusinessException;
import com.pro.common.api.model.ILoginInfo;
import com.pro.common.api.model.IUserIdClass;
import com.pro.common.api.model.auth.IOpenConfigClass;
import com.pro.common.modules.service.dependencies.commondata.model.CommonDataExportConfigData;
import com.pro.common.modules.service.dependencies.commondata.model.CommonDataExportField;
import com.pro.common.service.util.I18nUtils;
import com.pro.common.modules.service.dependencies.util.JsonKeyUnWrapper;
import com.pro.common.modules.service.dependencies.util.RequestUtil;
import com.pro.common.service.properties.CommonProperties;
import com.pro.framework.api.FrameworkConst;
import com.pro.framework.api.clazz.ClassCaches;
import com.pro.framework.api.database.AggregateResult;
import com.pro.framework.api.database.GroupBy;
import com.pro.framework.api.database.TimeQuery;
import com.pro.framework.api.database.page.IPageInput;
import com.pro.framework.api.database.page.PageInput;
import com.pro.framework.api.entity.IEntityProperties;
import com.pro.framework.api.enums.EnumCommonDataMethodType;
import com.pro.framework.api.enums.IEnumInt;
import com.pro.framework.api.enums.IEnumStr;
import com.pro.framework.api.model.IModel;
import com.pro.framework.api.model.IdsModel;
import com.pro.framework.api.structure.FirstHashMap;
import com.pro.framework.api.structure.Tuple3;
import com.pro.framework.api.util.AssertUtil;
import com.pro.framework.api.util.JSONUtils;
import com.pro.framework.api.util.StrUtils;
import com.pro.framework.javatodb.model.JTDFieldInfoDbVo;
import com.pro.framework.javatodb.model.JTDTableInfoVo;
import com.pro.framework.javatodb.service.IJTDService;
import com.pro.framework.mtq.service.multiwrapper.entity.IMultiPageResult;
import com.pro.framework.mtq.service.multiwrapper.util.MultiClassRelationFactory;
import com.pro.framework.mybatisplus.CRUDService;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.pro.framework.api.enums.EnumCommonDataMethodType.*;

/**
 * 数据权限
 *
 * @param <T>
 */
@Service
@Getter
@Slf4j
public class CommonDataService<T extends IModel> implements ICommonDataService<T> {
    @Autowired
    private CommonProperties commonProperties;
    @Autowired
    private CRUDService<T> crudService;
    @Autowired
    private CommonDataAuthService<T> commonDataAuthService;
    @Autowired
    private IEntityProperties entityProperties;
    @Autowired
    private IJTDService jtdService;
    //    @Autowired
//    private JsonServiceCamelCase jsonServiceCamelCase;
    @Autowired
    @Qualifier(FrameworkConst.JsonObjectMapper.multiTableQueryObjectMapper)
    private ObjectMapper multiTableQueryObjectMapper;

    @Override
    public IMultiPageResult<T> selectPage(ILoginInfo loginInfo, String entityClassNames, IPageInput pageInput, Map<String, Object> paramMap, TimeQuery timeQuery, UserDataQuery query) {
        List<Class> beanClasses = Arrays.stream(entityClassNames.split(",")).map(c -> (Class) getBeanClass(c)).toList();
        String entityClassNameFirst = entityClassNames.split(",")[0];
        Class<T> beanClass = getBeanClass(entityClassNameFirst);

        // 执行前 过滤数据来源
        commonDataAuthService.filterRequestQuery(selectPage, beanClass, beanClasses, loginInfo, paramMap, query,
                pageInput);

        IMultiPageResult<T> page = crudService.selectPage(loginInfo, entityClassNames, pageInput, paramMap, timeQuery, entityClassNameFirst);

        // 执行后 过滤数据结果
        page.setRecords(commonDataAuthService.filterEntity(selectPage, beanClass, loginInfo, page.getRecords()));
        return page;
    }


    @Override
    public List<AggregateResult> selectCountSum(ILoginInfo loginInfo, String entityClassName, PageInput pageInput, Map<String, Object> paramMap, TimeQuery timeQuery, GroupBy groupBy, UserDataQuery query) {
        List<Class> beanClasses = Arrays.stream(entityClassName.split(",")).map(c -> (Class) getBeanClass(c)).toList();
        Class<T> beanClass = getBeanClass(entityClassName);

        // 执行前 过滤数据来源
        commonDataAuthService.filterRequestQuery(selectCountSum, beanClass, beanClasses, loginInfo, paramMap, query,
                null);

        List<AggregateResult> results = crudService.selectCountSum(loginInfo, entityClassName, pageInput, paramMap, timeQuery,
                groupBy);

        for (AggregateResult result : results) {
            // 执行后 过滤数据结果
//            Stream.of("props", "avg", "countDistinct", "max", "min", "groupConcat").forEach(funPropName -> this.filterEntitySelectCountSum(entityClassName, beanClass, loginInfo, result, funPropName));

//            this.filterEntitySelectCountSum(entityClassName, beanClass, loginInfo, result, AggregateResult::getProps, AggregateResult::setProps, map -> {
//                try {
//                    String serialize = flexibleDateTimeObjectMapper.writeValueAsString(map);
//                    String content = JsonKeyUnWrapper.unwrapJsonKeys(serialize);
//                    T rs = flexibleDateTimeObjectMapper.readValue(content, beanClass);
//                    return rs;
//                } catch (JsonProcessingException e) {
//                    log.error("flexibleDateTimeObjectMapper rsMap={} paramMap={} =groupBy{}", JSONUtil.toJsonStr(map), JSONUtil.toJsonStr(paramMap), groupBy);
//                    throw  new RuntimeException(e);
//                }
//            });
            this.filterEntitySelectCountSumMap(entityClassName, beanClass, loginInfo, result, AggregateResult::getProps, AggregateResult::setProps, map -> {
                try {
                    String serialize = multiTableQueryObjectMapper.writeValueAsString(map);
                    String content = JsonKeyUnWrapper.unwrapJsonKeys(serialize);
                    return multiTableQueryObjectMapper.readValue(content, new TypeReference<>() {
                    });
                } catch (JsonProcessingException e) {
                    log.error("flexibleDateTimeObjectMapper rsMap={} paramMap={} =groupBy{}", JSONUtil.toJsonStr(map), JSONUtil.toJsonStr(paramMap), groupBy);
                    throw new RuntimeException(e);
                }
            });
            this.filterEntitySelectCountSum(entityClassName, beanClass, loginInfo, result, AggregateResult::getAvg, AggregateResult::setAvg);
            this.filterEntitySelectCountSum(entityClassName, beanClass, loginInfo, result, AggregateResult::getCountDistinct, AggregateResult::setCountDistinct);
            this.filterEntitySelectCountSum(entityClassName, beanClass, loginInfo, result, AggregateResult::getMax, AggregateResult::setMax);
            this.filterEntitySelectCountSum(entityClassName, beanClass, loginInfo, result, AggregateResult::getMin, AggregateResult::setMin);
            this.filterEntitySelectCountSum(entityClassName, beanClass, loginInfo, result, AggregateResult::getGroupConcat, AggregateResult::setGroupConcat);
        }
        return results;
    }


    @Override
    public List<T> selectList(ILoginInfo loginInfo, String entityClassNames, Map<String, Object> paramMap, TimeQuery timeQuery, UserDataQuery query, List<String> selects, PageInput pageInput) {
        List<Class> beanClasses = Arrays.stream(entityClassNames.split(",")).map(c -> (Class) getBeanClass(c)).toList();
        Class<T> beanClass = getBeanClass(entityClassNames.split(",")[0]);

//        Class<T> beanClass = getBeanClass(entityClassNames);
//        List<Class> beanClasses = Arrays.stream(entityClassNames.split(",")).map(c -> (Class) getBeanClass(c)).toList();

        // 执行前 过滤数据来源
        commonDataAuthService.filterRequestQuery(selectList, beanClass, beanClasses, loginInfo, paramMap, query,
                pageInput);
        List<String> selectLess = Collections.emptyList();
        switch (loginInfo.getSysRole()) {
            case ANONYMOUS:
            case USER:
                if (IOpenConfigClass.class.isAssignableFrom(beanClass)) {
                    paramMap.put("enabled", 1);
                }
                if (!IUserIdClass.class.isAssignableFrom(beanClass)) {
                    selectLess = Arrays.asList(
                            "createTime",
                            "updateTime",
//                            "deleted",
//                            "enabled",
//                            "sort",
                            "remark"
                    );
                }
                break;
        }
        List<T> list = crudService.selectList(loginInfo, entityClassNames, paramMap, timeQuery, selects, null,
                selectLess, pageInput);

        // 执行后 过滤数据结果
        return commonDataAuthService.filterEntity(selectList, beanClass, loginInfo, list);
    }

    @Override
    public T selectOne(ILoginInfo loginInfo, String entityClassName, IPageInput pageInput, Map<String, Object> paramMap, TimeQuery timeQuery, UserDataQuery query) {
        Class<T> beanClass = getBeanClass(entityClassName);
        List<Class> beanClasses = Arrays.stream(entityClassName.split(",")).map(c -> (Class) getBeanClass(c)).toList();

        // 执行前 过滤数据来源
        commonDataAuthService.filterRequestQuery(selectOne, beanClass, beanClasses, loginInfo, paramMap, query,
                pageInput);

        T entity = crudService.selectOne(loginInfo, entityClassName, pageInput, paramMap, timeQuery);

        // 执行后 过滤数据结果
        return commonDataAuthService.filterEntity(selectOne, beanClass, loginInfo, entity);
    }


    @Override
    public T selectById(ILoginInfo loginInfo, String entityClassName, Long id, UserDataQuery query) {
        List<Class> beanClasses = Arrays.stream(entityClassName.split(",")).map(c -> (Class) getBeanClass(c)).toList();

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("id", id);

        // 执行前 过滤数据来源
        Class<T> beanClass = getBeanClass(entityClassName);
        commonDataAuthService.filterRequestQuery(selectById, beanClass, beanClasses, loginInfo, paramMap, query, null);

        T entity = crudService.selectOne(loginInfo, entityClassName, null, paramMap, null);

        // 执行后 过滤数据结果
        return commonDataAuthService.filterEntity(selectById, beanClass, loginInfo, entity);
    }

    //
    @Override
    public T insertOrUpdate(ILoginInfo loginInfo, String entityClassName, String body) {
        Class<T> beanClass = getBeanClass(entityClassName);
        commonDataAuthService.filterRequest(selectById, beanClass, loginInfo);
        // 过滤实体
        T entityNew = this.filterEntityInsertUpdatePrepare(null, beanClass, loginInfo, entityClassName, body);
        crudService.insertOrUpdate(loginInfo, entityClassName, entityNew);
        return entityNew;
    }


    @Override
    public T insert(ILoginInfo loginInfo, String entityClassName, String body) {
        Class<T> beanClass = getBeanClass(entityClassName);
//        commonDataAuthService.filterRequest(selectById, beanClass, loginInfo);
        // 过滤实体
        T entityNew = this.filterEntityInsertUpdatePrepare(insert, beanClass, loginInfo, entityClassName, body);
        crudService.insert(loginInfo, entityClassName, entityNew);
        return entityNew;
    }

    @Override
    public Boolean update(ILoginInfo loginInfo, String entityClassName, String body) {
        Class<T> beanClass = getBeanClass(entityClassName);
        commonDataAuthService.filterRequest(selectById, beanClass, loginInfo);
        // 过滤实体
        T entityNew = this.filterEntityInsertUpdatePrepare(update, beanClass, loginInfo, entityClassName, body);
        crudService.updateById(loginInfo, entityClassName, entityNew);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateBatch(ILoginInfo loginInfo, String entityClassName, String body) {
        Class<T> beanClass = getBeanClass(entityClassName);
        commonDataAuthService.filterRequest(selectById, beanClass, loginInfo);
        // 过滤实体
        List<T> entityNewList = this.filterEntityUpdateBatchPrepare(update, beanClass, loginInfo, entityClassName,
                body);
        crudService.updateBatchById(loginInfo, entityClassName, entityNewList);
        return true;
    }

    @Override
    public Boolean saveBatch(ILoginInfo loginInfo, String entityClassName, String body) {
        Class<T> beanClass = getBeanClass(entityClassName);
//        commonDataAuthService.filterRequest(selectById, beanClass, loginInfo);
        // 过滤实体
        List<T> entityNewList = this.filterEntityUpdateBatchPrepare(insert, beanClass, loginInfo, entityClassName,
                body);
        crudService.saveBatch(loginInfo, entityClassName, entityNewList);
        return true;
    }

    @Override
    public Boolean delete(ILoginInfo loginInfo, String entityClassName, Long id) {
        Class<T> beanClass = getBeanClass(entityClassName);
        commonDataAuthService.filterRequest(selectById, beanClass, loginInfo);

        T entity = crudService.selectOneById(loginInfo, entityClassName, id);
        // 过滤实体
        commonDataAuthService.filterEntity(delete, beanClass, loginInfo, entity);
        crudService.delete(loginInfo, entityClassName, id);
        return true;
    }

    @Override
    public void export(List<CommonDataExportField> fields, ILoginInfo loginInfo, String entityClassName, PageInput page, Map<String, Object> paramMap, TimeQuery timeQuery, UserDataQuery query, PrintWriter responseWriter) {
        Class<T> beanClass = getBeanClass(entityClassName);
        Map<String, Tuple3<Field, Method, Method>> classMetaMap = ClassCaches.computeIfAbsentClassFieldMapFull(
                beanClass);
        if (fields == null) {
            JTDTableInfoVo tableInfo = jtdService.readTableInfo(MultiClassRelationFactory.INSTANCE.getEntityClass(
                    StrUtils.firstToLowerCase(beanClass.getSimpleName())));
            // 驼峰属性名
            List<JTDFieldInfoDbVo> fieldCfgs = tableInfo.getFields();
            fieldCfgs.forEach(field -> field.setFieldName(StrUtil.toCamelCase(field.getFieldName())));
            fields = fieldCfgs.stream()
                    .filter(f -> {
                        Tuple3<Field, Method, Method> classMeta = classMetaMap.get(f.getFieldName());
                        return !Long.class.equals(classMeta.getT1().getType());
                    }).map(f -> {
                        CommonDataExportField fieldConfigOne = new CommonDataExportField();
                        fieldConfigOne.setFieldName(f.getFieldName());
                        fieldConfigOne.setLabel(f.getLabel());
                        return fieldConfigOne;
                    }).collect(Collectors.toList());
        }
        List<String> selectFieldNames = fields.stream()
                .map(CommonDataExportField::getFieldName)
                .collect(Collectors.toList());
        selectFieldNames.add(0, "id");
        List<T> list = this.selectList(loginInfo, entityClassName, paramMap, timeQuery, query,
                selectFieldNames, page);


        CommonDataExportConfigData exportConfigData = new CommonDataExportConfigData();
        exportConfigData.setBoolTrueValue(translate(FrameworkConst.Str.TRUE_TRANSLATE_KEY));
        exportConfigData.setBoolFalseValue(translate(FrameworkConst.Str.FALSE_TRANSLATE_KEY));
        List<CommonDataExportField> finalFields = fields;

        List<String[]> rows = new ArrayList<>(list.size() + 1);
        // 写入表头
        rows.add(finalFields.stream()
                .map(CommonDataExportField::getLabel)
                .map(CommonDataService::translate)
                .toArray(String[]::new));
        for (T data : list) {
            rows.add(convertDataToCsvRow(data, finalFields, classMetaMap, exportConfigData));
        }
        CSVWriter writer = new CSVWriter(responseWriter);
        writer.writeAll(rows);
    }

    private static String translate(String label) {
        return StrUtils.or(I18nUtils.get(StrUtils.replaceSpecialToUnderline(label)), label);
    }

    private static <T extends IModel> String[] convertDataToCsvRow(T data, List<CommonDataExportField> fields, Map<String, Tuple3<Field, Method, Method>> classFieldMap, CommonDataExportConfigData exportConfigData) {
        return fields.stream()
                .map(f -> invokeAndToString(data, classFieldMap.get(f.getFieldName()).getT3(), exportConfigData))
                .toArray(String[]::new);
    }

    @SneakyThrows
    private static <T extends IModel> String invokeAndToString(T data, Method getMethod, CommonDataExportConfigData exportConfigData) {
        Object val = getMethod.invoke(data);
        if (val == null) {
            return null;
        } else {
            return valueRead(val, exportConfigData);
        }
    }


    private static String valueRead(Object o, CommonDataExportConfigData exportConfigData) {
        Class<?> aClass = o.getClass();
        if (Boolean.class.isAssignableFrom(aClass)) {
            return ((Boolean) o) ? exportConfigData.getBoolTrueValue() : exportConfigData.getBoolFalseValue();
        } else if (IEnumInt.class.isAssignableFrom(aClass)) {
            return ((IEnumInt) o).getLabel();
        } else if (IEnumStr.class.isAssignableFrom(aClass)) {
            return ((IEnumStr) o).getLabel();
        } else if (LocalDateTime.class.isAssignableFrom(aClass)) {
            return ((LocalDateTime) o).format(FrameworkConst.DateTimes.DATE_TIME_FORMAT);
        }
        return o.toString();
    }


    /**
     * 检查userId 过滤属性
     */
    private T filterEntityInsertUpdatePrepare(EnumCommonDataMethodType methodInput, Class<T> beanClass, ILoginInfo loginInfo, String entityClassName, String body) {
        T entityNew = JSONUtils.fromString(body, getBeanClass(entityClassName));
        T entityOld = null;
        EnumCommonDataMethodType methodById;
        Serializable id = entityNew.getId();
        // 新增
        if (id == null) {
            methodById = insert;
            AssertUtil.notEmpty(entityNew, "输入数据为空");
            entityOld = entityNew;
        }
        // 修改
        else {
            methodById = update;
            entityOld = crudService.selectOneById(loginInfo, entityClassName, id);
            AssertUtil.notEmpty(entityOld, "数据不存在");
        }
        if (methodInput != null) {
            boolean isOK = methodById.equals(methodInput);
            if (!isOK) {
                log.warn("entityClassName {} methodById= {} and methodInput={} is not consistent| {}", entityClassName, methodById, methodInput, RequestUtil.getCurrentRequestUrl());
                throw new BusinessException("新增不能传ID_修改必须传ID");
            }
        }
        return commonDataAuthService.filterEntity(methodById, beanClass, loginInfo, entityNew, entityOld);
    }

    public static void main(String[] args) {
        log.warn("methodById=" + " is not consistent", new Exception());

    }

    /**
     * 检查userId 过滤属性
     */
    private List<T> filterEntityUpdateBatchPrepare(EnumCommonDataMethodType methodInput, Class<T> beanClass, ILoginInfo loginInfo, String entityClassName, String body) {
//        Class<T> beanClass = getBeanClass(entityClassName);
        if (JSONUtil.isTypeJSONArray(body)) {
            return JSONUtil.toList(body, beanClass);
        } else {
            T entityNew = JSONUtils.fromString(body, beanClass);
            AssertUtil.isTrue(entityNew instanceof IdsModel, "请输入Ids");
            //noinspection DataFlowIssue
            List<Long> ids = ((IdsModel) entityNew).getIds().stream().filter(Objects::nonNull).toList();
            if (ids.isEmpty()) {
                return Collections.emptyList();
            }

            return ids.stream().map(idOne -> {
                T copyObject = copyObject(idOne, entityNew);
                T entityOld = crudService.selectOneById(loginInfo, entityClassName, idOne);
                AssertUtil.notEmpty(entityOld, "数据不存在");
                return commonDataAuthService.filterEntity(update, beanClass, loginInfo, copyObject, entityOld);
            }).toList();
        }
    }

    @SneakyThrows
    private T copyObject(Long idOne, T entityNew) {
        //noinspection unchecked,deprecation
        T clone = (T) entityNew.getClass().newInstance();
        BeanUtil.copyProperties(entityNew, clone);
        clone.setId(idOne);
        return clone;
    }
//
//    @SuppressWarnings({"rawtypes", "unchecked"})
//    private void filterEntitySelectCountSumProp(
//            String entityClassName,
//            Class<T> beanClass,
//            ILoginInfo loginInfo,
//            AggregateResult result,
//            Function<AggregateResult, FirstHashMap> getFun,
//            BiConsumer<AggregateResult,FirstHashMap> setFun
//    ) {
////        HashMap<String, ?> map = BeanUtil.getProperty(result, funPropName);
//        FirstHashMap<String, Object> map = getFun.apply(result);
//        Map<String, ?> data = map.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().replace(entityClassName + ".", ""), Map.Entry::getValue));
//        //noinspection deprecation

    /// /        T entity = BeanUtil.mapToBean(data, beanClass, true);
//        T entity = jsonServiceCamelCase.deserialize(jsonServiceCamelCase.serialize(data), beanClass);
//        setFun.accept(result, (FirstHashMap<String, Object>) BeanUtil.beanToMap(commonDataAuthService.filterEntity(selectCountSum, beanClass, loginInfo, entity)));
//    }

//    @SuppressWarnings({"rawtypes", "unchecked"})
//    private <PROP extends FirstHashMap> void filterEntitySelectCountSum(
//            String entityClassName,
//            Class<T> beanClass,
//            ILoginInfo loginInfo,
//            AggregateResult result,
//            Function<AggregateResult, PROP> getFun,
//            BiConsumer<AggregateResult, PROP> setFun
//    ) {

    /// /        HashMap<String, ?> map = BeanUtil.getProperty(result, funPropName);
//        PROP map = getFun.apply(result);
//        Map<String, ?> data = ((Map<String, ?>) map).entrySet()
//                .stream()
//                .collect(Collectors.toMap(e -> e.getKey().replace(entityClassName + ".", ""), Map.Entry::getValue));
//        //noinspection deprecation
//        T entity = jsonServiceCamelCase.deserialize(jsonServiceCamelCase.serialize(data), beanClass);
//        //noinspection unchecked
//        T entityFilter = commonDataAuthService.filterEntity(selectCountSum, beanClass, loginInfo, entity);
//        setFun.accept(result, (PROP) new FirstHashMap<>(BeanUtil.beanToMap(entityFilter)));
//    }

//    private <PROP extends FirstHashMap<String, Object>> void filterEntitySelectCountSum(
//            String entityClassName,
//            Class<T> beanClass,
//            ILoginInfo loginInfo,
//            AggregateResult result,
//            Function<AggregateResult, PROP> getFun,
//            BiConsumer<AggregateResult, PROP> setFun
//    ) {
//        PROP map = getFun.apply(result);
//        Map<String, ?> data = ((Map<String, ?>) map).entrySet()
//                .stream()
//                .collect(Collectors.toMap(e -> e.getKey().replace(entityClassName + ".", ""), Map.Entry::getValue));
//        //noinspection deprecation
//        T entity = BeanUtil.mapToBean(data, beanClass, true);
//
//        T entityFilter = commonDataAuthService.filterEntity(selectCountSum, beanClass, loginInfo, entity);
//        //noinspection rawtypes,unchecked
//        setFun.accept(result, (PROP) new FirstHashMap(BeanUtil.beanToMap(entityFilter)));
//    }
    private <PROP extends FirstHashMap<String, ?>> void filterEntitySelectCountSum(
            String entityClassName,
            Class<T> beanClass,
            ILoginInfo loginInfo,
            AggregateResult result,
            Function<AggregateResult, PROP> getFun,
            BiConsumer<AggregateResult, PROP> setFun
    ) {
        this.filterEntitySelectCountSum(entityClassName, beanClass, loginInfo, result, getFun, setFun, map -> BeanUtil.mapToBean(map, beanClass, true));
    }

    private <PROP extends FirstHashMap<String, ?>> void filterEntitySelectCountSum(
            String entityClassName,
            Class<T> beanClass,
            ILoginInfo loginInfo,
            AggregateResult result,
            Function<AggregateResult, PROP> getFun,
            BiConsumer<AggregateResult, PROP> setFun,
            Function<Map<String, ?>, T> mapToEntityFun
    ) {
        PROP map = getFun.apply(result);
        Map<String, Object> rs;
        if (map.isEmpty()) {
            rs = Collections.emptyMap();
        } else {
            Map<String, Object> data = new HashMap<>();
            map.forEach((key, value) -> {
                String newKey = key.replace(entityClassName + ".", "");
                data.put(newKey, value);
            });
            T entity = mapToEntityFun.apply(data);
            T entityFilter = commonDataAuthService.filterEntity(selectCountSum, beanClass, loginInfo, entity);
            rs = BeanUtil.beanToMap(entityFilter);
        }
        //noinspection rawtypes,unchecked
        setFun.accept(result, (PROP) new FirstHashMap(rs));
    }

    private void filterEntitySelectCountSumMap(
            String entityClassName,
            Class<T> beanClass,
            ILoginInfo loginInfo,
            AggregateResult result,
            Function<AggregateResult, FirstHashMap<String, ?>> getFun,
            BiConsumer<AggregateResult, FirstHashMap<String, ?>> setFun,
            Function<FirstHashMap<String, ?>, FirstHashMap<String, ?>> mapToEntityFun
    ) {
        FirstHashMap<String, ?> map = getFun.apply(result);
        FirstHashMap<String, Object> mapTemp = new FirstHashMap<>();
        map.forEach((key, value) -> {
            String newKey = key.replace(entityClassName + ".", "");
            mapTemp.put(newKey, value);
        });
        FirstHashMap<String, ?> mapTemp2 = commonDataAuthService.filterEntityMap(selectCountSum, beanClass, loginInfo, mapToEntityFun.apply(mapTemp));
        setFun.accept(result, mapTemp2);
    }

    @Override
    public Class<T> getBeanClass(String entityClassName) {
        Class<T> tClass = MultiClassRelationFactory.INSTANCE.getEntityClass(entityClassName);
        AssertUtil.notEmpty(tClass, "_类不存在", entityClassName);
        return tClass;
    }

}
